package com.yxy.utils;

import com.yxy.constant.StatusConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
public class ExcelUtil {

    private static final String DIR = "excel";
    private static final String SIGHTS_SHEET_NAME = "sightsBooking";
    private static final String HOTEL_SHEET_NAME = "hotelBooking";
    public static final String SIGHTS = "sights";
    public static final String HOTEL = "hotel";
    public static final String URL = "http://tourism.ymvpear.icu/";
    private static final Object[][] STATUS_ARR = new Object[][]{
            {"已取消", StatusConstant.BOOKING_CANCEL},
            {"已预约", StatusConstant.BOOKING_OK},
            {"已使用", StatusConstant.BOOKING_USER},
            {"已过期", StatusConstant.BOOKING_EXPIRED},
    };

    public static <T> String exportToExcel(List<T> dataList, String filePath) throws IOException, NoSuchFieldException, IllegalAccessException {
        // 创建工作簿
        Workbook workbook = new XSSFWorkbook();
        // 创建工作表
        Sheet sheet = workbook.createSheet(filePath.equals(SIGHTS) ? SIGHTS_SHEET_NAME : HOTEL_SHEET_NAME);

        // 创建标题行
        List<String> attributes = getAttributes(dataList);
        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < attributes.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(attributes.get(i));
        }

        // 填充数据
        int rowNum = 1;
        for (T data : dataList) {
            Row row = sheet.createRow(rowNum++);
            for (int i = 0; i < attributes.size(); i++) {
                // 获取 data 对象中指定字段的 Field 对象。
                Field field = data.getClass().getDeclaredField(attributes.get(i));
                // 设置字段为可访问状态，即使它是私有的
                field.setAccessible(true);
                // 获取字段在 data 对象中的实际值。
                Object value = field.get(data);
                row.createCell(i).setCellValue(value.toString());
            }
        }

        // 状态提示
        Row row = sheet.createRow(++rowNum);
        // 创建单元格并设置值
        Cell cell = row.createCell(0);
        cell.setCellValue("status详情");
        // 合并单元格 (起始行, 结束行, 起始列, 结束列)
        sheet.addMergedRegion(new CellRangeAddress(
                rowNum, // 起始行
                rowNum, // 结束行
                0, // 起始列
                1 // 结束列
        ));
        // 设置样式
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER); // 居中对齐
        // 设置字体颜色
        Font font = workbook.createFont();
        font.setColor(IndexedColors.RED.getIndex());
        style.setFont(font);
        cell.setCellStyle(style);
        // 填充状态详情
        for (int i = 0; i < 4; i++) {
            Row detailRow = sheet.createRow(++rowNum);
            for (int j = 0; j < 2; j++) {
                Cell detailCell = detailRow.createCell(j);
                detailCell.setCellValue(STATUS_ARR[i][j].toString());
                detailCell.setCellStyle(style);
            }
        }

        // 获取当前日期并格式化为字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate currentDate = LocalDate.now();
        String currentDateString = currentDate.format(formatter);

        // 获取前一天的日期
        LocalDate previousDate = currentDate.minusDays(1);
        String previousDateString = previousDate.format(formatter);

        // 判断文件夹类型并生成文件路径
        String fullDirectory = DIR + File.separator + currentDateString;

        // 创建当天日期的文件夹（如果不存在）
        File currentDir = new File(fullDirectory);
        if (!currentDir.exists()) {
            currentDir.mkdirs();
        }

        // 删除当天之前的所有文件夹
        deletePreviousDirectories(DIR, currentDateString);

        // 组装完整路径
        String path = fullDirectory + File.separator + filePath + ".xlsx";
        // 写入文件
        try (FileOutputStream fileOut = new FileOutputStream(path)) {
            workbook.write(fileOut);
        } catch (IOException e) {
            log.info("文件写入失败");
        }

        // 关闭工作簿
        workbook.close();

        // 返回文件下载路径
        return URL + path;
    }

    /**
     * 通过反射获取所有属性
     *
     * @param dataList
     * @return 返回属性列表
     */
    private static <T> List<String> getAttributes(List<T> dataList) {
        if (dataList == null || dataList.isEmpty()) {
            log.info("数据列表为空");
            return null;
        }
        // 获取泛型类型T的Class对象
        T firstElement = dataList.get(0);
        Class<?> clazz = firstElement.getClass();

        // 获取所有字段（包括私有字段）
        Field[] fields = clazz.getDeclaredFields();

        List<String> fieldList = new ArrayList<>();
        for (Field field : fields) {
            fieldList.add(field.getName());
        }
        return fieldList;
    }

    /**
     * 删除指定目录前的所有文件夹
     *
     * @param directory 根目录（hotel/sights)
     * @param baseDate  当前日期
     */
    private static void deletePreviousDirectories(String directory, String baseDate) {
        File baseDir = new File(directory);
        if (!baseDir.exists() || !baseDir.isDirectory()) {
            log.info("指定路径不存在后不是一个目录：{}", directory);
            return;
        }

        // 将基准日期转换为时间戳
        long baseTimestamp = covertDateToTimestamp(baseDate);
        if (baseTimestamp == -1) {
            log.info("无效基准日期：{}", baseDate);
            return;
        }

        // 遍历目录下的所有子文件夹
        for (File subDir : baseDir.listFiles()) {
            if (subDir.isDirectory()) {
                try {
                    // 提取文件夹名称并解析为时间戳
                    long subDirTimestamp = covertDateToTimestamp(subDir.getName());
                    if (subDirTimestamp != -1 && subDirTimestamp < baseTimestamp) {
                        // 删除早于基准日期的文件夹及其文件
                        deleteDirectory(subDir);
                        log.info("已删除文件夹：{}", subDir.getAbsolutePath());
                    }
                } catch (Exception e) {
                    log.info("无法解析文件夹：{}", subDir.getName());
                }
            }
        }
    }

    /**
     * 辅助方法：递归删除文件夹
     *
     * @param directory
     */
    private static void deleteDirectory(File directory) {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteDirectory(file); // 递归删除子文件夹
                    } else {
                        file.delete(); // 删除文件
                    }
                }
            }
        }
        directory.delete(); // 删除空文件夹
    }

    /**
     * 将日期字符串转换为时间戳
     *
     * @param dateStr
     * @return
     */
    private static long covertDateToTimestamp(String dateStr) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse(dateStr);
            return date.getTime();
        } catch (Exception e) {
            return -1;
        }
    }
}
